import Vue from 'vue'
import Vuex from 'vuex'
import { encryptPassword } from '@/api/password-client'
import api, { ApiError } from '@/api'
import theme from 'muse-ui/lib/theme'
import { TypeAnalyzer, SystemConfigure } from '@/util'
import { initialize, fetchPublicInfo } from '@/api/mixed-requests'

Vue.use(Vuex)

const config = new SystemConfigure([
  {
    name: 'night_mode',
    default: false,
    mutation: 'SET_NIGHT_MODE'
  },
  {
    name: 'is_phone',
    default: false,
    mutation: 'SET_IS_PHONE'
  },
  {
    name: 'pagin',
    default: 'auto',
    mutation: 'SET_PAGIN'
  },
  {
    name: 'qc_mode',
    default: 'poll',
    mutation: 'SET_QUESTION_CREATE_MODE'
  },
  {
    name: 'qc_config',
    default: {
      type_id: 0,
      style: 0,
      has_image: true,
      option_count: 4,
      clip: 'auto',
      preview: true
    },
    mutation: 'SET_QUESTION_CREATE_CONFIG'
  },
  {
    name: 'aside_menu',
    default: {
      questions: true,
      exam: false,
      check: false
    },
    mutation: 'SET_ASIDE_MENU'
  }
])

export default new Vuex.Store({
  state: {
    initializing: true,
    initializeError: null,
    publickey: null,
    nightMode: false, // 是否是夜间模式
    isPhone: false, // 是否是手机版
    pagin: 'auto', // 页码显示位置
    questionCreateMode: 'poll', // 出题模式 form poll mixed
    questionCreateConfig: {
      type_id: 0, // 默认类型id
      style: 0, // 默认形式
      has_image: true, // 是否上传图片
      option_count: 4, // 默认选项个数
      clip: 'manual', // 裁剪模式 off auto manual
      preview: true // 上传前预览
    },
    questionCreateForm: {
      type_id: 0,
      style: 0,
      text: '',
      image: null,
      options: [],
      answer: ''
    },
    asideMenu: {
      questions: true,
      exam: false,
      check: false
    },
    phoneAsideDrawer: false, // 手机版侧边栏是否显示
    currentUser: {
      id: 0, //  ID
      username: '', //  用户名
      password: '', //  密码（加密后）
      realname: '', //  真实姓名
      role: 0, //  用户权限
      is_superadmin: false, //  是否是超级管理员
      is_active: false, //  是否启用
      register_at: 0, //  注册时间
      last_login_at: 0 //  最后登录
    },
    version: {
      lastest: {
        code: 0,
        text: ''
      },
      min: {
        code: 0,
        text: ''
      },
      current: {
        code: parseInt(process.env.VUE_APP_VERSION),
        text: process.env.VUE_APP_VERSION_TEXT
      }
    },
    privateMessageCount: {
      read_count: 0,
      received_count: 0
    },
    types: [],
    permissions: [],
    roles: [],
    contacts: [],
    questionQueryCache: {
      status: 'all',
      style: 'all',
      keyword: 'off',
      content: ''
    }
  },
  getters: {
    initializing: state => state.initializing,
    initializeError: state => state.initializeError,
    publickey: state => state.publickey,
    encrypter: state => state.encrypter,
    version: state => state.version,
    privateMessageCount: state => state.privateMessageCount,
    types: state => state.types,
    permissions: state => state.permissions,
    roles: state => state.roles,
    contacts: state => state.contacts,
    nightMode: state => state.nightMode,
    isPhone: state => state.isPhone,
    pagin: state => state.pagin,
    questionCreateMode: state => state.questionCreateMode,
    questionCreateConfig: state => state.questionCreateConfig,
    questionCreateForm: state => state.questionCreateForm,
    phoneAsideDrawer: state => state.phoneAsideDrawer,
    asideMenu: state => state.asideMenu,
    currentUser: state => state.currentUser,
    currentUserId: state => state.currentUser ? state.currentUser.id : 0,
    questionQueryCache: state => state.questionQueryCache,
    isLogin: (_, getters) => getters.currentUser && getters.currentUser.id !== 0,
    getTypeTextById: state => id => {
      const type = state.types.find(item => item.id === id)
      return type ? type.text : '未知类型'
    },
    currentUserPermissions: state => {
      const roleCode = state.currentUser ? state.currentUser.role : 0
      const role = state.roles.find(it => it.id === roleCode)
      if (!role) {
        return []
      }
      const allPermissions = state.permissions
      const currentPermissions = role.permissions
      const result = []
      for (const permId of currentPermissions) {
        const perm = allPermissions.find(it => it.id === permId)
        if (perm) {
          result.push(perm)
        }
      }
      return result
    },
    currentUserHasPermissionByCode: (_, getters) => code => {
      const isSuperAdmin = getters.currentUser ? getters.currentUser.is_superadmin : false
      if (isSuperAdmin) return true
      const currentUserCodes = getters.currentUserPermissions.map(it => it.code)
      return currentUserCodes.indexOf(code) >= 0
    },
    getUserById: state => id => {
      return state.contacts.find(it => it.id === id) || null
    }
  },
  mutations: {
    SET_INITIALIZING(state, initializing) {
      state.initializing = initializing
    },
    SET_INITIALIZE_ERROR(state, error) {
      state.initializeError = error
    },
    SET_PUBLIC_KEY(state, key) {
      state.publickey = key
    },
    SET_VERSION(state, version) {
      state.version.lastest.code = version.lastest_version
      state.version.min.code = version.min_version
      state.version.lastest.text = version.lastest_version_text
      state.version.min.text = version.min_version_text
    },
    SET_PRIVATE_MESSAGE_COUNT(state, value) {
      state.privateMessageCount = value
    },
    SET_CURRENT_USER(state, currentUser) {
      state.currentUser = currentUser
    },
    SET_QUESTION_QUERY_CACHE(state, cache) {
      state.questionQueryCache = cache
    },
    SET_TYPES(state, types) {
      const analyzer = new TypeAnalyzer(types)
      state.types = analyzer.analyze()
    },
    SET_PERMISSIONS(state, permissions) {
      state.permissions = permissions
    },
    SET_ROLES(state, roles) {
      state.roles = roles
    },
    SET_CONTACTS(state, contacts) {
      state.contacts = contacts
    },
    SET_NIGHT_MODE(state, value) {
      state.nightMode = value
      if (value) {
        theme.use('dark')
      } else {
        theme.use('light')
      }
      config.write('SET_NIGHT_MODE', value)
    },
    SET_IS_PHONE(state, value) {
      state.isPhone = value
      config.write('SET_IS_PHONE', value)
    },
    SET_PAGIN(state, value) {
      state.pagin = value
      config.write('SET_PAGIN', value)
    },
    SET_QUESTION_CREATE_MODE(state, value) {
      state.questionCreateMode = value
      config.write('SET_QUESTION_CREATE_MODE', value)
    },
    SET_QUESTION_CREATE_CONFIG(state, value) {
      state.questionCreateConfig = value
      config.write('SET_QUESTION_CREATE_CONFIG', value)
    },
    SET_QUESTION_CREATE_FORM(state, value) {
      state.questionCreateForm = value
    },
    SET_PHONE_ASIDE_DRAWER(state, phoneAsideDrawer) {
      state.phoneAsideDrawer = phoneAsideDrawer
    },
    SET_ASIDE_MENU(state, value) {
      state.asideMenu = value
      config.write('SET_ASIDE_MENU', value)
    }
  },
  actions: {
    /**
     * 初始化
     */
    async initialize({ dispatch, commit }) {
      try {
        dispatch('loadSystemConfig')
        const solve = (mutation, value) => {
          if (value instanceof ApiError) {
            throw value
          } else if (value !== null) {
            commit(mutation, value)
          }
        }
        const {
          version,
          publickey,
          currentUser,
          permissions,
          roles,
          types,
          contacts,
          privateMessageCount
        } = await initialize()
        solve('SET_VERSION', version)
        solve('SET_PUBLIC_KEY', publickey.key)
        solve('SET_CURRENT_USER', currentUser)
        solve('SET_PERMISSIONS', permissions)
        solve('SET_ROLES', roles)
        solve('SET_TYPES', types)
        solve('SET_CONTACTS', contacts)
        solve('SET_PRIVATE_MESSAGE_COUNT', privateMessageCount)
        commit('SET_INITIALIZING', false)
      } catch (error) {
        commit('SET_INITIALIZE_ERROR', error)
      }
    },
    /**
     * 加载系统配置
     */
    async loadSystemConfig({ commit }) {
      config.load(commit)
    },
    /**
     * 登录
     */
    async login({ getters, commit, dispatch }, { username, password }) {
      const publickey = getters.publickey
      const payload = encryptPassword(publickey, password)
      const user = await api.login(username, payload)
      commit('SET_CURRENT_USER', user)
      dispatch('fetchPublicInfo').catch(() => null)
      return user
    },
    /**
     * 登出
     */
    async logout({ commit }) {
      await api.logout()
      commit('SET_CURRENT_USER', null)
      commit('SET_PERMISSIONS', [])
      commit('SET_ROLES', [])
      commit('SET_TYPES', [])
    },
    /**
     * 获取权限相关参数
     */
    async fetchPublicInfo({ commit }) {
      const solve = (mutation, value) => {
        if (value instanceof ApiError) {
          throw value
        } else if (value !== null) {
          commit(mutation, value)
        }
      }
      const {
        permissions,
        roles,
        types,
        contacts,
        privateMessageCount
      } = await fetchPublicInfo()
      solve('SET_PERMISSIONS', permissions)
      solve('SET_ROLES', roles)
      solve('SET_TYPES', types)
      solve('SET_CONTACTS', contacts)
      solve('SET_PRIVATE_MESSAGE_COUNT', privateMessageCount)
    },
    /**
     * 更新私信个数
     */
    async fetchPrivateMessageCount({ commit }) {
      const data = await api.getPrivateMessageCount()
      commit('SET_PRIVATE_MESSAGE_COUNT', data)
    }
  }
})
